package com.gzmu.myprint.vo;


import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.gzmu.myprint.model.PayInfo;
import com.itextpdf.text.pdf.PdfReader;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import static com.gzmu.myprint.constant.Constant.*;

/**
 * Created by Hyman on 2017/2/28.
 */
public class CommonUtil {
    static final int wdDoNotSaveChanges = 0;// 不保存待定的更改。
    static final int wdFormatPDF = 17;// word转PDF 格式

    public static String getRandomOrderId() {
        // UUID.randomUUID().toString().replace("-","")
        Random random = new Random(System.currentTimeMillis());
        int value = random.nextInt();
        while (value < 0) {
            value = random.nextInt();
        }
        return value + "";
    }

    private static XStream xstream = new XStream(new XppDriver() {
        public HierarchicalStreamWriter createWriter(Writer out) {
            return new PrettyPrintWriter(out) {
                //增加CDATA标记
                boolean cdata = true;
                @SuppressWarnings("rawtypes")
                public void startNode(String name, Class clazz) {
                    super.startNode(name, clazz);
                }
                protected void writeText(QuickWriter writer, String text) {
                    if (cdata) {
                        writer.write("<![CDATA[");
                        writer.write(text);
                        writer.write("]]>");
                    } else {
                        writer.write(text);
                    }
                }
            };
        }
    });

    public static String payInfoToXML(PayInfo pi) {
        xstream.alias("xml", pi.getClass());
        return xstream.toXML(pi);
    }

    @SuppressWarnings("unchecked")
    public static Map<String, String> parseXml(String xml) throws Exception {
        Map<String, String> map = new HashMap<String, String>();
        Document document = DocumentHelper.parseText(xml);
        Element root = document.getRootElement();
        List<Element> elementList = root.elements();
        for (Element e : elementList)
            map.put(e.getName(), e.getText());
        return map;
    }


    public static String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
            //多次反向代理后会有多个ip值，第一个ip才是真实ip
            int index = ip.indexOf(",");
            if(index != -1){
                return ip.substring(0,index);
            }else{
                return ip;
            }
        }
        ip = request.getHeader("X-Real-IP");
        if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
            return ip;
        }
        return request.getRemoteAddr();
    }


    /**
     * 对字符串md5加密
     *
     * @param str
     * @return
     */
    public static String getMD5(String str) throws Exception {
        try {
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md.update(str.getBytes());
            // digest()最后确定返回md5 hash值，返回值为8为字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
            return new BigInteger(1, md.digest()).toString(16);
        } catch (Exception e) {
            throw new Exception("MD5加密出现错误");
        }
    }

    /**
     * 计算Word转化成的pdf格式文档的页数
     * @param filepath 文件路径
     * @return pagecount页数
     */
    public static int getPdfPage(String filepath){
        int pagecount = 0;
        PdfReader reader;
        try {
            reader = new PdfReader(filepath);
            pagecount= reader.getNumberOfPages();
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(pagecount);
        return pagecount;
    }

    /**
     * 将Word文件装换为PDF格式的
     * @param source 源文件路径
     * @return 表示转换是否成功
     */
    public static int getWordPage(String source) {
        System.out.println("+++Word to PDF start...");
        long start = System.currentTimeMillis();
        ActiveXComponent app = null;
        String target = "E:\\opDf.pdf";
        try {
            app = new ActiveXComponent("Word.Application");
            // 设置word不可见
            app.setProperty("Visible", new Variant(false));
            Dispatch word  = app.getProperty("Documents").toDispatch();

            System.out.println("file：" + source);
//            Dispatch doc = Dispatch.call(docs, "Open", source, false, true).toDispatch();
//            System.out.println("PDF：" + target);
//            Dispatch.call(doc, "SaveAs:", target, wdFormatPDF);
//            Dispatch.call(doc, "Close:", false);
            Dispatch doc = Dispatch.invoke(
                    word ,
                    "Open",
                    Dispatch.Method,
                    new Object[] { source, new Variant(false),
                            new Variant(true) }, new int[1]).toDispatch();
            System.out.println("word to PDF..." + target);
            Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] {target, new Variant(17) }, new int[1]);
            Dispatch.call(doc, "Close", new Variant(false));
            //Dispatch.call(docs, "Close:", false);
            //app.safeRelease();
            long end = System.currentTimeMillis();
            System.out.println("time：" + (end - start) + "ms");
            int pages =  getPdfPage(target);
            File tofile = new File(target);
            tofile.delete();
            return pages;
        } catch (Exception e) {
            System.out.println("error：" + e.getMessage());
            return 0;
        } finally {
            if (app != null) {
                app.invoke("Quit", wdDoNotSaveChanges);
            }
        }
    }

    public static long getFilePages(String name, String type){
        long pages;
        if (type.equals("docx") || type.equals("doc"))
            pages = getWordPage(name);
        else if(type.equals("jpg") || type.equals("bmp"))
            pages = 1;
        else
            pages = getPdfPage(name);
        return pages;
    }

    public static String getOpenid(String code, String appid, String appsecret) {
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid +
                "&secret=" + appsecret + "&js_code=" + code + "&grant_type=authorization_code";
        HttpUtil httpUtil = new HttpUtil();
        try {
            HttpResult httpResult = httpUtil.doGet(url, null, null);
            if(httpResult.getStatusCode() == 200) {
                JsonParser jsonParser = new JsonParser();
                JsonObject obj = (JsonObject) jsonParser.parse(httpResult.getBody());
                System.out.println("+++obj: " + obj.toString());

                if(obj.get("errcode") != null) {
                    System.out.println("+++obj returns errcode: " + obj.get("errcode"));
                    return null;
                } else {
                    return obj.get("openid").toString();
                }
                //return httpResult.getBody();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getVerification(String mobile) {
        String str="0123456789";
        String uuid= new String();
        for(int i=0;i<4;i++) {
            char ch = str.charAt(new Random().nextInt(str.length()));
            uuid += ch;
        }
        String url = "https://way.jd.com/chonry/smsapi?sign=" + APP_SIGN +  "&mobile=" +
                mobile + "&content=" + SMS_CONTENT + uuid +"。&appkey=" + SMS_KEY;
        HttpUtil httpUtil = new HttpUtil();
        try {
            HttpResult httpResult = httpUtil.doGet(url, null,null);
            if(httpResult.getStatusCode() == 200) {
                JsonParser jsonParser = new JsonParser();
                JsonObject obj = (JsonObject) jsonParser.parse(httpResult.getBody());
                System.out.println("+++obj: " + obj.toString());

                if(obj.get("code") != null) {
                    return obj.get("scode").toString();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
